#include "task.h"
#include "schedule.h"
#include "mem.h"
#include <string.h>
#include <stdlib.h>
#include <stddef.h>
#include "mem.h"
#define OS_INVALID    (unsigned int)(-1) 
struct taskTCB* g_idleTaskTCB = NULL;
uint32_t g_idleTaskID ;
struct osTask  g_osTask;
extern void archOsStart();
static void taskExit(void)
{


}

static void* taskStackInit(void(*entry)(void*),void* stackBase,uint32_t stackSize)
{
   context_t* context =(context_t*)((uint32_t)stackBase + stackSize - sizeof(struct context_t));
   memset(context,0xCC,sizeof(context_t));
   context->sp = (uint32_t)stackBase + stackSize;
   context->lr = (uint32_t)taskExit;
   context->pc = (uint32_t)entry;
   context->spsr = 0x6000001f;
   return(void*) context;

}


void createTask(taskParam* taskParam,char* name)
{
    taskTCB* task = (struct taskTCB*)malloc(sizeof(struct taskTCB)); 
    uint8_t* stackPoint = malloc(taskParam->stackSize);
    task->priority = taskParam->priority;
    task->taskId = taskParam->taskId;
    task->stackPoint = (uint32_t*)taskStackInit(taskParam->entry,stackPoint,taskParam->stackSize);  
    add_timer(task);
    scheduleInsert(task);
    if(task->taskId == g_idleTaskID){
        g_idleTaskTCB = task;
    }
    printf("%s 0x%x stackPoint 0x%x\n",name,task,task->stackPoint);
}

void setScheduleIdleParam(struct taskTCB* task)
{
    task->state |= TASK_STATUS_DELAY;
}


static void idleTask(void* argc)
{
    uart_puts("idleTask\n");    
    while(1){
        asm volatile ("WFI");
    }
}


void createIdleTask(void)
{
    taskParam taskParam;
    taskParam.taskId = g_idleTaskID;
    taskParam.stackSize = 1024;
    taskParam.priority = 31;
    taskParam.entry = idleTask; 
    createTask(&taskParam,"idleTask");
    setScheduleIdleParam(g_idleTaskTCB);
    g_idleTaskTCB->waitTime = 0;
}



extern void archOsStart();
void startOs(void)
{
    struct taskTCB* task = getScheduleTaskTop();
    g_osTask.taskRun = g_osTask.taskNew  = task;
    printf("first run task=0x%x\n",task);
    task->state |= TASK_STATUS_RUNNING;
    archOsStart();
}

void taskInit(void)
{
    memset(&g_osTask,0, sizeof(g_osTask));
    g_idleTaskID = OS_INVALID;
    g_idleTaskTCB = NULL;
}



